﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using SupervisedSpeakerRecognition;
using ZedGraph;


namespace speakerReco
{

    public partial class MainWindow : Form
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        public System.Drawing.Color[] COLROS = new Color[6] { Color.Blue, Color.Green, Color.Red, Color.Purple, Color.Red, Color.Black };
        String[] Filenames;
        WMPLib.WindowsMediaPlayer Player;
        // FileDetails [] filedetails=new FileDetails [100];
        List<FileDetails> filedetails = new List<FileDetails>();
        LogicLayerManager LM;
        List<FileDetails> points = new List<FileDetails>();
        ZedGraphControl zgc = new ZedGraphControl();// zedGraphControl_SVMModel;
        GraphPane myPane;//= zgc.GraphPane;
        Settings Set;
        HashSet<string> groups = new HashSet<string>();
        private void PlayFile(String url)
        {
            Player = new WMPLib.WindowsMediaPlayer();
            Player.PlayStateChange +=
                new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(Player_PlayStateChange);
            Player.MediaError +=
                new WMPLib._WMPOCXEvents_MediaErrorEventHandler(Player_MediaError);
            Player.URL = url;
            Player.controls.play();
        }
        private void Player_PlayStateChange(int NewState)
        {
            if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsStopped)
            {

            }
        }

        private void Player_MediaError(object pMediaObject)
        {
            MessageBox.Show("Cannot play media file.");

        }

        private void browserbtn_Click(object sender, EventArgs e)
        {
            openFileDialogWaves.ShowDialog();
        }

        private void DelBtn_Click(object sender, EventArgs e)
        {
            if (FilesTable.CurrentRow.Index < filedetails.Count)
            {
                if (FilesTable.CurrentRow.Cells[1].Value!=null)
                       groups.Remove(FilesTable.CurrentRow.Cells[1].Value.ToString());
                RmoveFromList(FilesTable.CurrentRow.Cells[0].Value.ToString());
                FilesTable.Rows.Remove(FilesTable.CurrentRow);
            }
        }

        private void Play_Click(object sender, EventArgs e)
        {

            PlayFile(filedetails[FilesTable.CurrentRow.Index].FilePath);

        }

        private void openFileDialogWaves_FileOk(object sender, CancelEventArgs e)
        {
            Filenames = openFileDialogWaves.FileNames;

            for (int i = 0; i < Filenames.Length; i++)
            {
                FileInfo info = new FileInfo(Filenames[i]);
                FilesTable.Rows.Add(info.Name);
                FileDetails FD = new FileDetails(info.FullName);
                filedetails.Add(FD);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {

            if (CheckTable())
            {

                //List<FileDetails> FilesList = new List<FileDetails>();
                //for(int i=0;i<filesCounter;i++)
                //{

                //    FilesList.Add(filedetails[i]);

                //}

                LM = new LogicLayerManager(filedetails);
                if (useDefultMenuItem.Checked)
                    LM.useDefaultMFCCManagerParameters();
                else
                    LM.initMFCCManager("Hamming", Set.Alpha, Set.WinSize, Set.Overlap, true, Set.Stripsl, Set.RealOnly, true, Set.PowMag, Set.UseFirstco, Set.GetHighFreq, 16);
                //ProgressBar pb = new ProgressBar();
                //System.Windows.Forms.Label l = new System.Windows.Forms.Label();//temp
                points = LM.buildSVMModle(toolStripProgressBar1, StripLable);
                DrawZgraph1(points, null, LM.SVMpoints,groups.Count);
                AnaButon.Visible = true;
                //if (Filenames.Length > 2)
                //    LM.analyse(pb, l, 2);

            }
            else
                MessageBox.Show("You Must Set Group To Each File", "Error", MessageBoxButtons.OK);
        }

        public bool CheckTable()
        {
            foreach (FileDetails file in filedetails)
                if (file.Group == null)
                    return false;
            return true;

        }

        private void DrawZgraph(List<FileDetails> points, FileDetails prediction_point, List<PointD> SvmPoits)
        {
            zgc = zedGraphControl_SVMModel;
            myPane = zgc.GraphPane;
            zgc.Dock = DockStyle.Fill;
            zgc.GraphPane.CurveList.Clear();
            zgc.GraphPane.GraphObjList.Clear();
            zgc.Visible = true;


            // Set the title and axis labels
            myPane.Title.Text = "SVM Model Graph";
            //myPane.XAxis.Title.Text = "X Axis";
            //myPane.YAxis.Title.Text = "Y Axis";

            PointPairList list1 = new PointPairList();
            PointPairList list2 = new PointPairList();
            PointPairList list3 = new PointPairList();

            double sum_group1_x = 0;
            double sum_group1_y = 0;
            int size_group1 = 0;
            double sum_group2_x = 0;
            double sum_group2_y = 0;
            int size_group2 = 0;

            List<double> x = new List<double>();
            List<double> y = new List<double>();
            foreach (PointD p in SvmPoits)
            {
                x.Add(p.X);
                y.Add(p.Y);

            }
            for (int i = 0; i < points.Count; i++)
            {
                if (points[i].Group == "1")
                {
                    list1.Add(points[i].Point.X, points[i].Point.Y, 1);
                    sum_group1_x += points[i].Point.X;
                    sum_group1_y += points[i].Point.Y;
                    size_group1++;
                }
                else
                {

                    list2.Add(points[i].Point.X, points[i].Point.Y, 2);
                    sum_group2_x += points[i].Point.X;
                    sum_group2_y += points[i].Point.Y;
                    size_group2++;

                }
            }

            /******Adding Regression Line*******/

            //PointPairList data = new PointPairList(x.ToArray(), y.ToArray());
            //myPane.AddCurve("Data", data, Color.Red);
            //LineItem myLine = (LineItem)myPane.CurveList[0];
            //myLine.Line.IsVisible = false;
            ////Calculate the regression
            //double slope = CoVariance(x.ToArray(), y.ToArray()) / Variance(x.ToArray());
            //double offset = (1.0 / (x.Count) * (y.Sum() - (slope * x.Sum())));
            ////Calculate the R squared
            //double totalSOS = 0;
            //double regressionSOS = 0;

            if (prediction_point != null)
                list3.Add(prediction_point.Point.X, prediction_point.Point.Y, 2);

            sum_group1_x = sum_group1_x / size_group1;
            sum_group1_y = sum_group1_y / size_group1;
            sum_group2_x = sum_group2_x / size_group2;
            sum_group2_y = sum_group2_y / size_group2;

            if (prediction_point != null)
            {
                LineItem myCurve3 = myPane.AddCurve("Prediction", list3, Color.Red, SymbolType.Circle);
                myCurve3.Symbol.Size = 14;
                myCurve3.Symbol.Border.IsVisible = false;
                myCurve3.Symbol.Fill.Type = FillType.Brush;
                myCurve3.Line.IsVisible = false;
            }
            LineItem myCurve1 = myPane.AddCurve("Group " + Convert.ToString(1), list1, Color.Blue, SymbolType.Circle);
            myCurve1.Symbol.Size = 14;
            myCurve1.Symbol.Border.IsVisible = false;
            myCurve1.Symbol.Fill.Type = FillType.Brush;
            myCurve1.Line.IsVisible = false;

            LineItem myCurve2 = myPane.AddCurve("Group " + Convert.ToString(2), list2, Color.Green, SymbolType.Circle);
            myCurve2.Symbol.Size = 14;
            myCurve2.Symbol.Border.IsVisible = false;
            myCurve2.Symbol.Fill.Type = FillType.Brush;
            myCurve2.Line.IsVisible = false;

            TextObj text = new TextObj("group 1", sum_group1_x, sum_group1_y, CoordType.AxisXYScale);
            text.FontSpec.FontColor = Color.Blue; //Color.Blue;
            text.FontSpec.IsBold = true;
            text.FontSpec.Border.IsVisible = false;
            text.FontSpec.Fill.IsVisible = false;
            text.FontSpec.Size = 14;
            myPane.GraphObjList.Add(text);

            text = new TextObj("group 2", sum_group2_x, sum_group2_y, CoordType.AxisXYScale);
            text.FontSpec.FontColor = Color.Green;
            text.FontSpec.IsBold = true;
            text.FontSpec.Border.IsVisible = false;
            text.FontSpec.Fill.IsVisible = false;
            text.FontSpec.Size = 14;
            myPane.GraphObjList.Add(text);


            //myPane.XAxis.MajorGrid.IsVisible = true;
            //myPane.YAxis.MajorGrid.IsVisible = true;

            //Plot the data
            // myPane.Title.Text = "ZedGraph Regression";
            //PointPairList data = new PointPairList(x, y);
            //LineItem myLine = (LineItem)myPane.CurveList[0];
            //myLine.Line.IsVisible = false;
            myPane.XAxis.Scale.FontSpec.Size = 14;
            myPane.XAxis.Title.FontSpec.Size = 14;
            myPane.YAxis.Scale.FontSpec.Size = 14;
            myPane.YAxis.Title.FontSpec.Size = 14;
            myPane.Legend.IsVisible = true;
            myPane.Chart.Fill = new Fill(Color.LightBlue, Color.FromArgb(255, 255, 166), 90F);
            //******RegrssionLine***********

            //for (int i = 0; i < x.Count; i++)
            //{
            //    totalSOS = totalSOS + Math.Pow((y[i] - y.Average()), 2);
            //    regressionSOS = regressionSOS + Math.Pow(((slope * x[i]) + offset) - y.Average(), 2);
            //}
            //double rSquared = regressionSOS / totalSOS;
            ////Plot the regression line
            ////PlotRegressionLine(slope, offset, x.Min(), x.Max());
            ////Add textbox with regression values
            //AddNumbers(rSquared, slope, offset);

            zgc.AxisChange();
            zgc.Update();
            zgc.Refresh();
        }
        private void DrawZgraph1(List<FileDetails> points, FileDetails prediction_point, List<PointD> SvmPoits,int numberOflists)
        {
            zgc = zedGraphControl_SVMModel;
            myPane = zgc.GraphPane;
            zgc.Dock = DockStyle.Fill;
            zgc.GraphPane.CurveList.Clear();
            zgc.GraphPane.GraphObjList.Clear();
            zgc.Visible = true;


            // Set the title and axis labels
            myPane.Title.Text = "SVM Model Graph";
            //myPane.XAxis.Title.Text = "X Axis";
            //myPane.YAxis.Title.Text = "Y Axis";

            PointPairList list1 = new PointPairList();
            PointPairList[] list = new PointPairList[numberOflists+1];
            double [] sum_group_x  = new double [numberOflists] ;
            double[] sum_group_y = new double[numberOflists ];
            double[] size_group = new double[numberOflists];
            
            List<double> x = new List<double>();
            List<double> y = new List<double>();

            foreach (PointD p in SvmPoits)
            {
                x.Add(p.X);
                y.Add(p.Y);

            }
            for (int i=0;i<numberOflists+1;i++)
            {
                list[i] = new PointPairList();
            }
            for (int i = 0; i < points.Count; i++)
            {

                list[int.Parse(points[i].Group) - 1].Add(points[i].Point.X, points[i].Point.Y, int.Parse(points[i].Group));
                sum_group_x[int.Parse(points[i].Group) - 1] += points[i].Point.X;
                sum_group_y[int.Parse(points[i].Group) - 1] += points[i].Point.Y;
                size_group[int.Parse(points[i].Group) - 1]++;
            }
          

            /******Adding Regression Line*******/

            //PointPairList data = new PointPairList(x.ToArray(), y.ToArray());
            //myPane.AddCurve("Data", data, Color.Red);
            //LineItem myLine = (LineItem)myPane.CurveList[0];
            //myLine.Line.IsVisible = false;
            ////Calculate the regression
            //double slope = CoVariance(x.ToArray(), y.ToArray()) / Variance(x.ToArray());
            //double offset = (1.0 / (x.Count) * (y.Sum() - (slope * x.Sum())));
            ////Calculate the R squared
            //double totalSOS = 0;
            //double regressionSOS = 0;

            if (prediction_point != null)
                list[numberOflists].Add(prediction_point.Point.X, prediction_point.Point.Y, 2);

            for (int i = 0; i < numberOflists; i++)
            {
                sum_group_x[i] = sum_group_x[i] / size_group[i];
                sum_group_y[i] = sum_group_y[i] / size_group[i];
            }
         

            if (prediction_point != null)
            {
                LineItem myCurve3 = myPane.AddCurve("Prediction", list[numberOflists], COLROS[numberOflists], SymbolType.Circle);
                myCurve3.Symbol.Size = 14;
                myCurve3.Symbol.Border.IsVisible = false;
                myCurve3.Symbol.Fill.Type = FillType.Brush;
                myCurve3.Line.IsVisible = false;
            }
            for (int i = 0; i < numberOflists; i++)
            {
                LineItem myCurve = myPane.AddCurve("Group " + Convert.ToString(i+1), list[i], COLROS[i], SymbolType.Circle);
                myCurve.Symbol.Size = 14;
                myCurve.Symbol.Border.IsVisible = false;
                myCurve.Symbol.Fill.Type = FillType.Brush;
                myCurve.Line.IsVisible = false;
 
            }

            for (int i = 0; i < numberOflists; i++)
            {
                TextObj text = new TextObj("group" + Convert.ToString(i + 1), sum_group_x[i], sum_group_y[i], CoordType.AxisXYScale);
                text.FontSpec.FontColor = COLROS[i]; //Color.Blue;
                text.FontSpec.IsBold = true;
                text.FontSpec.Border.IsVisible = false;
                text.FontSpec.Fill.IsVisible = false;
                text.FontSpec.Size = 14;
                myPane.GraphObjList.Add(text);
            }


            //myPane.XAxis.MajorGrid.IsVisible = true;
            //myPane.YAxis.MajorGrid.IsVisible = true;

            //Plot the data
            // myPane.Title.Text = "ZedGraph Regression";
            //PointPairList data = new PointPairList(x, y);
            //LineItem myLine = (LineItem)myPane.CurveList[0];
            //myLine.Line.IsVisible = false;
            myPane.XAxis.Scale.FontSpec.Size = 14;
            myPane.XAxis.Title.FontSpec.Size = 14;
            myPane.YAxis.Scale.FontSpec.Size = 14;
            myPane.YAxis.Title.FontSpec.Size = 14;
            myPane.Legend.IsVisible = true;
            myPane.Chart.Fill = new Fill(Color.LightBlue, Color.FromArgb(255, 255, 166), 90F);
            //******RegrssionLine***********

            //for (int i = 0; i < x.Count; i++)
            //{
            //    totalSOS = totalSOS + Math.Pow((y[i] - y.Average()), 2);
            //    regressionSOS = regressionSOS + Math.Pow(((slope * x[i]) + offset) - y.Average(), 2);
            //}
            //double rSquared = regressionSOS / totalSOS;
            ////Plot the regression line
            ////PlotRegressionLine(slope, offset, x.Min(), x.Max());
            ////Add textbox with regression values
            //AddNumbers(rSquared, slope, offset);

            zgc.AxisChange();
            zgc.Update();
            zgc.Refresh();
        }

        private void FilesTable_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex > -1 && e.RowIndex < filedetails.Count)
            {
                drawWav(filedetails[FilesTable.CurrentCell.RowIndex].FilePath);
                if (e.ColumnIndex == 1)
                {

                    if (FilesTable.CurrentCell.Value == null)
                        FilesTable.CurrentCell.Value = "1";
                    else
                    {
                        string value = FilesTable.CurrentCell.Value.ToString();
                        value = Convert.ToString(int.Parse(value)+1);
                        FilesTable.CurrentCell.Value = (object)value;
                    }
                    groups.Add(FilesTable.CurrentCell.Value.ToString());
                    //if (FilesTable.CurrentCell.Value == "1")
                    //    FilesTable.CurrentCell.Value = "2";
                    //else
                    //    if (FilesTable.CurrentCell.Value == "2")
                    //        FilesTable.CurrentCell.Value = "3";
                    if (filedetails[e.RowIndex] != null)
                        filedetails[e.RowIndex].Group = FilesTable.CurrentCell.Value.ToString();
                }
            }
        }

        private void AnalyzeDialog_FileOk(object sender, CancelEventArgs e)
        {
            //FilesTable.CurrentRow.DefaultCellStyle.SelectionForeColor = Color.Red;
            //FilesTable.CurrentRow.DefaultCellStyle.SelectionBackColor = Color.Blue;
            FileInfo info = new FileInfo(AnalyzeDialog.FileName);
            FilesTable.Rows.Add(info.Name);
            FileDetails prediction = new FileDetails(info.FullName, "0");
            //LM.initMFCCManager("Hamming",
            prediction = LM.analyse(toolStripProgressBar1, StripLable, prediction);
            DrawZgraph1(points, prediction, LM.SVMpoints, groups.Count);
            PredictLabel.Text = "The Predicted Group Is: Group " + prediction.Group;
            StripLable.Text = "Prediction Completed";
            StripLable.Update();

        }

        private void RmoveFromList(String WavName)
        {
            foreach (FileDetails fd in filedetails)
            {
                if (fd.FilePath.Contains(WavName))
                {
                    filedetails.Remove(fd);
                    return;
                }
            }

        }

        private void drawWav(String fileName)
        {
            WavFileExtractorCommand wavReadCmd = new WavFileExtractorCommand();
            wavReadCmd.FilePath = fileName;
            wavReadCmd.UsingStereo = true;
            wavReadCmd.execute();
            double[] wavData = wavReadCmd.OutPutWithOutHeader;
            double maxWav = findMaxValueInArray(wavData);
            // Set up for drawing in the Wav Data Picture Box
            Bitmap canvasWav = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            drawTimeDomainOutputData(wavData, Color.LimeGreen, pictureBox1, canvasWav, 0, maxWav);
        }

        private void drawTimeDomainOutputData(double[] wave, Color col, PictureBox pictureBox, Bitmap canvasTimeDomain, int type, double maxYval)
        {
            Graphics offScreenDC = Graphics.FromImage(canvasTimeDomain);
            SolidBrush brush = new System.Drawing.SolidBrush
                        (Color.FromArgb(0, 0, 0));
            Pen pen = new System.Drawing.Pen(col);

            // Determine channel boundaries
            long width = canvasTimeDomain.Width;
            long center = canvasTimeDomain.Height / 2;
            long height = canvasTimeDomain.Height;
            //offScreenDC.DrawLine(pen, 0, center, width, center);
            long left = 0;
            long top = 0;
            long right = width;
            long bottom = height;
            // Draw channel
            double yCenter = (bottom - top) / 2;
            double yScale = 0.5 * (bottom - top) / maxYval;
            //  for FFT 
            if (type == 1)
            {
                yScale = (-1) * (bottom - top) / maxYval;
                yCenter = bottom - 4;
            }
            // for MFFC display graph
            if (type == 2)
            {
                yScale = (-1) * (bottom - top) / maxYval;
                yCenter = bottom - 4;
            }
            // a 16 bit sample has values from -32768 to 32767
            long xPrev = 0, yPrev = 0;
            for (long xAxis = left; (xAxis < right) && (xAxis < wave.Length); xAxis++)
            {
                long xStep = wave.Length / (right - left) * xAxis;
                if (wave.Length < width)
                    xStep = xAxis;
                long yAxis = (long)(yCenter + (wave[xStep] * yScale));
                if (xAxis == 0)
                {
                    xPrev = 0;
                    yPrev = yAxis;
                }
                else
                {
                    offScreenDC.DrawLine(pen, xPrev, yPrev, xAxis, yAxis);
                    xPrev = xAxis;
                    yPrev = yAxis;
                }
            }

            // Clean up
            pictureBox.Image = canvasTimeDomain;
            offScreenDC.Dispose();
        }
        private double findMaxValueInArray(double[] array)
        {
            double max = array[0];
            for (int i = 1; i < array.Length; i++)
            {
                if (array[i] > max)
                    max = array[i];
            }
            return max;
        }

        private void customSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            useDefultMenuItem.Checked = false;
            Set = new Settings();
            Set.ShowDialog();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        public static double Variance(double[] Data)
        {
            double sum = 0;
            double average = Data.Average();
            foreach (double value in Data)
            {
                sum += Math.Pow((value - average), 2);
            }
            double result = sum / (Data.GetLength(0));
            return result;
        }

        public static double CoVariance(double[] data1, double[] data2)
        {
            double result = 0;
            double avgX = data1.Average();
            double avgY = data2.Average();
            for (int i = 0; i < data1.GetLength(0); i++)
            {
                result = result + ((data1[i] - avgX) * (data2[i] - avgY));
            }
            return result / data1.GetLength(0);
        }


        private void PlotRegressionLine(double slope, double offset, double min, double max)
        {
            PointPairList regressionLine = new PointPairList();
            regressionLine.Add(min, (min * slope) + offset);
            regressionLine.Add(max, (max * slope) + offset);
            LineItem RegressionLine = new LineItem("Fitted Line", regressionLine, Color.Blue, SymbolType.None);
            RegressionLine.Line.StepType = StepType.NonStep;
            RegressionLine.Line.Width = 2;
            RegressionLine.Symbol.IsVisible = false;
            myPane.CurveList.Add(RegressionLine);
            myPane.Legend.IsVisible = false;
        }

        private void AddNumbers(double rSquared, double slope, double ofset)
        {
            //TextObj text = new TextObj("R-Squared: " + Math.Round(rSquared, 2) + "\nSlope: " + Math.Round(slope, 2) + "\nOffset: " + Math.Round(ofset, 2), 0.2, 0.2, CoordType.ChartFraction);
            // myPane.GraphObjList.Add(text);
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            zedGraphControl_SVMModel.SaveAsBitmap();
        }

        private void AnaButon_Click(object sender, EventArgs e)
        {
            AnalyzeDialog.ShowDialog();
        }

        private void FilesTable_KeyUp(object sender, KeyEventArgs e)
        {
            if (FilesTable.CurrentRow.Index > -1 && FilesTable.CurrentRow.Index < filedetails.Count)
            {
                if (FilesTable.CurrentCell.ColumnIndex == 1)
                {
                    if (filedetails[FilesTable.CurrentRow.Index] != null)
                        filedetails[FilesTable.CurrentRow.Index].Group = FilesTable.CurrentCell.Value.ToString();
                }
            }

        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            About ab = new About();
            ab.ShowDialog();

        }

        private void browserbtn_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Load Files";
        }

        private void DelBtn_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Delete Selected File";
        }

        private void Play_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Play Selected File";
        }

        private void Stop_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Stop Playing";
        }

        private void browserbtn_MouseLeave(object sender, EventArgs e)
        {
            toolStripLabel.Text = "";
        }

        private void AnaButon_MouseLeave(object sender, EventArgs e)
        {
            toolStripLabel.Text = "";
        }

        private void SVMBttn_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Start Build SVM Model";
        }

        private void AnaButon_MouseEnter(object sender, EventArgs e)
        {
            toolStripLabel.Text = "Press To Select a New Speaker and Analayze it's Group";
        }

       


       



    }
}

